﻿using System;
using System.Net;
using System.Net.Sockets;
using System.Collections.Generic;
using System.Text;

class ClientState
{
	public Socket socket; 
	public byte[] readBuff = new byte[1024]; 
}

class MainClass
{
	//监听Socket
	static Socket listenfd;
	//客户端Socket及状态信息
	static Dictionary<Socket, ClientState> clients = new Dictionary<Socket, ClientState>();
    
    public static void Main (string[] args)
	{
		//Socket
		listenfd = new Socket(AddressFamily.InterNetwork,
			SocketType.Stream, ProtocolType.Tcp);
		//Bind
		IPAddress ipAdr = IPAddress.Parse("127.0.0.1");
		IPEndPoint ipEp = new IPEndPoint(ipAdr, 8888);
		listenfd.Bind(ipEp);
		//Listen
		listenfd.Listen(0);
		Console.WriteLine("[服务器]启动成功");
		//主循环
		while(true){
			//检查listenfd
			if(listenfd.Poll(0, SelectMode.SelectRead)){
				ReadListenfd(listenfd);
			}
			//检查clientfd
			foreach (ClientState s in clients.Values){
				Socket clientfd = s.socket;
				if(clientfd.Poll(0, SelectMode.SelectRead)){
					if(!ReadClientfd(clientfd)){
						break;
					}
				}
			}
			//防止cpu占用过高
			System.Threading.Thread.Sleep(1);
		}

	}

	//读取Listenfd
	public static void ReadListenfd(Socket listenfd){
		Console.WriteLine("Accept");
		Socket clientfd = listenfd.Accept();
		ClientState state = new ClientState();
		state.socket = clientfd;
		clients.Add(clientfd, state);
	}

    //读取Clientfd
    const string formatter = "{0,0}{1,5}\n{2,0}";
    const string receive = "Receive";
    static StringBuilder sb = new StringBuilder();
    public static bool ReadClientfd(Socket clientfd){
		ClientState state = clients[clientfd];
		int count = clientfd.Receive(state.readBuff);
		//客户端关闭
		if(count == 0){
			clientfd.Close();
			clients.Remove(clientfd);
			Console.WriteLine("Socket Close");
			return false;
		}
        //显示
        //取出消息体长度  因为使用了UInt16 占两个字节 所以写了固定长度2 合理的写法是:sizeof(UInt16)
        UInt16 bodyLength = BitConverter.ToUInt16(state.readBuff, 0);
        string recvStr = System.Text.Encoding.UTF8.GetString(state.readBuff, 2, count-2);
        sb.Append(bodyLength.ToString());
        sb.Append(recvStr);
        Console.WriteLine(formatter, receive, bodyLength, recvStr);
        Console.WriteLine(formatter, receive, count, sb.ToString());
        sb.Clear();
        //Console.WriteLine("Receive 包体" + bodyLength + "个字节："+ recvStr);
        //Console.WriteLine("Receive 包体和长度信息："+count + recvStr1);
        //广播 你好
        byte[] sendBytes = new byte[count];
        Array.Copy(state.readBuff, 0, sendBytes, 0, count);
		foreach (ClientState cs in clients.Values){
			cs.socket.Send(sendBytes);
		}
		return true;
	}
}

